package com.wmd.validation.aop;

import com.alibaba.fastjson.JSON;
import com.wmd.core.util.StringUtil;
import com.wmd.core.util.TimeTool;
import com.wmd.core.util.YKArrayUtils;
import com.wmd.validation.LogInterfaceHistory.InterfaceHistory;
import com.wmd.validation.LogInterfaceHistory.InterfaceUser;
import com.wmd.validation.annotation.MyMethod;
import com.wmd.validation.LogInterfaceHistory.LogHistory;
import com.wmd.validation.util.LogMessage;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import org.springframework.validation.BindingResult;
import org.springframework.web.context.request.RequestAttributes;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.Method;

/**
 * 日志管理
 * 
 * @author yincheng lu
 * @time 2018年12月26日下午1:29:39
 * @Description
 */
@Aspect
@Component // ("prototype")
@Order(1)
public class LogManage {

//	@Pointcut("execution(public * *..controller..*.*(..)) && @annotation(com.wmd.validation.annotation.MyMethod)") // ||(execution(*
	@Pointcut("@annotation(com.wmd.validation.annotation.MyMethod)") // ||(execution(*
	public static void webLog() {
	}


	private final Log logger = LogFactory.getLog(this.getClass());
	public static final ThreadLocal<LogMessage> tl_msg = ThreadLocal.withInitial(() -> new LogMessage());
	public static final String VALIDATE_USER="VALIDATE_USER";
	/**
	 * 记录方法开始执行的时间 author:yincheng lu Last_update 2018年12月26日下午2:01:07
	 * 
	 * @param joinPoint
	 */
	@Before("webLog()")
	public void doBeforeInServiceLayer(JoinPoint joinPoint) {
		LogMessage hm = tl_msg.get();
		/*
		 * System.out.println("start!******"); System.out.println(hm);
		 * this.printOptLog();
		 */
		// logger.info(hm);
		hm.setStartTimeMillis(System.currentTimeMillis());// ; // 记录方法开始执行的时间
		// logger.info("start!"+new SimpleDateFormat("yyyy-MM-dd
		// HH:mm:ss").format(hm.getStartTimeMillis()));
	}

	/**
	 * 记录结束时间 author:yincheng lu Last_update 2018年12月26日下午2:01:29
	 * 
	 * @param joinPoint
	 */
	@After("webLog()")
	public void doAfterInServiceLayer(JoinPoint joinPoint) {
		LogMessage hm = tl_msg.get();
		hm.setEndTimeMillis(System.currentTimeMillis()); // 记录方法执行完成的时间
		// logger.info("end!"+new SimpleDateFormat("yyyy-MM-dd
		// HH:mm:ss").format(tl_msg.get().getEndTimeMillis()));
//		printOptLog(hm, this.logHistory);
//		hm.printLog();
	}

	/**
	 * 获取切面拦截方法 author:yincheng lu Last_update 2019年1月8日上午10:45:29
	 * 
	 * @param pjp
	 * @return
	 * @throws NoSuchMethodException
	 * @throws SecurityException
	 */
	public static Method getProceedJoinPointMethod(ProceedingJoinPoint pjp)
			throws NoSuchMethodException, SecurityException {
		Method method = ((MethodSignature) pjp.getSignature()).getMethod();
		Method realMethod = pjp.getTarget().getClass().getDeclaredMethod(method.getName(), method.getParameterTypes());
		return realMethod;
	}

	/**
	 * 环绕触发 author:yincheng lu Last_update 2018年12月26日下午2:01:38
	 * 
	 * @param pjp
	 * @return
	 * @throws Throwable
	 */
	@Around("webLog()")
	public Object doAround(ProceedingJoinPoint pjp) throws Throwable {
		LogMessage hm = tl_msg.get();
		//Method method = ((MethodSignature) pjp.getSignature()).getMethod();
		Method realMethod =getProceedJoinPointMethod(pjp); 
		MyMethod an = realMethod.getAnnotation(MyMethod.class);
		RequestAttributes ra = RequestContextHolder.getRequestAttributes();
		ServletRequestAttributes sra = (ServletRequestAttributes) ra;
		HttpServletRequest request = sra.getRequest();

		Object[] arguments = pjp.getArgs();//实际参数
		hm.setArguments(YKArrayUtils.getOtherClassFromArray(arguments, BindingResult.class, MultipartFile.class,HttpServletRequest.class, HttpServletResponse.class));

		fitLogMessage(hm, an, request);
		// HttpSession session = request.getSession();
		// 执行完方法的返回值：调用proceed()方法，就会触发切入点方法执行
		Object result = pjp.proceed();// result的值就是被拦截方法的返回值
		// logger.info(result.getClass());
		hm.setOutputParamMap(result);
		return result;
		/*
		 * if (yk_user.getStatus() != 0) { HttpMessage result =
		 * HttpMessage.create(HttpCode.USER_PERMISSION_DENIED, "账号异常！", null);
		 * hm.setStartTimeMillis(System.currentTimeMillis());
		 * hm.setOutputParamMap(result); return result.toJSONString(); } else { Object
		 * result = pjp.proceed();// result的值就是被拦截方法的返回值 logger.info(result.getClass());
		 * return result; }
		 */

	}

	/**
	 * 装配Log bean author:yincheng lu Last_update 2019年1月3日上午11:05:18
	 * 
	 * @param hm
	 * @param an
	 * @param request
	 */
	public static void fitLogMessage(LogMessage hm, MyMethod an, HttpServletRequest request) {
/*		if (result instanceof HttpMessage) {
			hm.setCode(((HttpMessage) result).getCode());
		}*/
		if(an!=null){
			hm.setMethodName(an.value());

		}

		// HttpSession session = request.getSession();
		hm.setInputParamMap(request.getParameterMap());
		hm.setRequestPath(request.getRequestURI());
		InterfaceUser yk_user = (InterfaceUser) request.getAttribute(VALIDATE_USER);
		if (yk_user != null) {
			hm.setUserName(yk_user.getName());
			hm.setUser_id(yk_user.getUSER_ID());
		} else {
			hm.setUserName("未知用户");
			hm.setUser_id("0");
		}
		// 执行完方法的返回值：调用proceed()方法，就会触发切入点方法执行

	}

	/**
	 * 输出日志 author:yincheng lu Last_update 2018年12月26日下午2:14:07
	 */
	public static void printOptLog(int code,LogHistory logHistory) {
		LogMessage hm = tl_msg.get();
		if(StringUtil.isEmpty(hm.getRequestPath())){
			return;
		}
		hm.setCode(code);
		/*
		 * String optTime = new
		 * SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(hm.getStartTimeMillis());
		 * logger.info("--------> user：" + hm.getUserName() + "  url：" +
		 * hm.getRequestPath() + "; op_time：" + optTime + " pro_time：" +
		 * (hm.getEndTimeMillis() - hm.getStartTimeMillis()) + "ms ;" + "method:" +
		 * hm.getMethodName() + "; param：" + JSON.toJSONString(hm.getInputParamMap()) +
		 * ";" + " result：" + JSON.toJSONString(hm.getOutputParamMap()));
		 */
		hm.printLog();
		if ("0".equals(hm.getUser_id())) {// 不记录未知用户的访问记录
			return;
		}
		if(logHistory!=null){
			InterfaceHistory ykInterfaceHistory = new InterfaceHistory();
			ykInterfaceHistory.setCODE(hm.getCode());
			ykInterfaceHistory.setHTTP_RETURN(JSON.toJSONString(hm.getOutputParamMap()));
			ykInterfaceHistory.setMETHOD(hm.getMethodName());
			ykInterfaceHistory.setPRO_TIME(Integer.parseInt(hm.getEndTimeMillis() - hm.getStartTimeMillis() + ""));
			ykInterfaceHistory.setTIME(TimeTool.getTime(TimeTool.simpleDateFormat_1));
			ykInterfaceHistory.setUSER_ID(hm.getUser_id());
			logHistory.insertSelective(ykInterfaceHistory);
		}
	}
}
